﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using Saber.Infrastructure;
using Saber.Infrastructure.Storage;

namespace Saber.Plugin.Folder
{
    public class Main : IPlugin, ISettingProvider, ISavable
    {
        //private static List<string> _driverNames;
        private PluginInitContext _context;

        private readonly Settings _settings;
        private readonly PluginJsonStorage<Settings> _storage;


        private static PluginMetadata metadata;

        static Main()
        {
            metadata = new PluginMetadata();
            metadata.ID = "B4D3B69656E14D44865C8D818EAE47C4";
            metadata.Name = "文件夹";
            metadata.Description = "在Saber中直接打开收藏的文件夹，或者根据路径和提示打开任意文件夹。";
            metadata.ActionKeyword = "open";
            metadata.IcoPath = "Images\\folder.png";
        }

        public Main()
        {
            _storage = new PluginJsonStorage<Settings>();
            _settings = _storage.Load();
            //InitialDriverList();
        }

        public void Save()
        {
            _storage.Save();
        }

        public Control CreateSettingPanel()
        {
            return new FileSystemSettings(_context.API, _settings);
        }

        public void Init(PluginInitContext context)
        {
            _context = context;

        }

        public List<Result> Query(Query query)
        {
            List<Result> results = _settings.FolderLinks.AsParallel().Where(
                f => query.Search.Length<=0 || StringMatcher.Score(f.Path, query.Search) > 0 || StringMatcher.ScoreForPinyin(f.Path, query.Search) > 0
                ).Select(
                    item => new Result()
                    {
                        Title = item.NickName,
                        IcoPath = item.Path,
                        SubTitle = item.Path,
                        Score = 10,
                        Action = c =>
                        {
                            _context.API.ChangeQuery($"{query.ActionKeyword} {item.Path}{(item.Path.EndsWith("\\") ? "" : "\\")}");
                            return false;
                        },
                        ContextData = item,
                    }).ToList();


            //if (_driverNames != null && !_driverNames.Any(query.Search.StartsWith))
            //{
            //    return results;
            //}

            //if (!input.EndsWith("\\"))
            //{
            //    //"c:" means "the current directory on the C drive" whereas @"c:\" means "root of the C drive"
            //    input = input + "\\";
            //}
            results.AddRange(QueryInternal_Directory_Exists(query));

            return results;
        }
        //private void InitialDriverList()
        //{
        //    if (_driverNames == null)
        //    {
        //        _driverNames = new List<string>();
        //        DriveInfo[] allDrives = DriveInfo.GetDrives();
        //        foreach (DriveInfo driver in allDrives)
        //        {
        //            _driverNames.Add(driver.Name.ToLower().TrimEnd('\\'));
        //        }
        //    }
        //}

        private List<Result> QueryInternal_Directory_Exists(Query query)
        {
            String search = query.Search.ToLower();
            var results = new List<Result>(); 
            if (search.Length <= 0)
            {
                return results;
            }

            string incompleteName = "";
            if (!Directory.Exists(search + "\\"))
            {
                //if the last component of the path is incomplete,
                //then make auto complete for it.
                int index = search.LastIndexOf('\\');

                if (index == -1)
                {
                    index = search.IndexOf(':');
                }

                if (index > 0 && index < (search.Length - 1))
                {
                    incompleteName = search.Substring(index + 1).ToLower();
                    search = search.Substring(0, index + 1) + "\\";
                    if (!Directory.Exists(search))
                        return results;
                }
                else
                    return results;
            }

            search = search.EndsWith("\\") ? search : search + "\\";


            if (incompleteName.Length <= 0 && Directory.Exists(search))
            {
                results.Add(new Result
                {
                    Title = "打开当前文件夹",
                    IcoPath = "Images\\open.png",
                    SubTitle = search,
                    Score = 10000,
                    Action = c =>
                    {
                        Process.Start(search);
                        return true;
                    }
                });
            }


            //添加子文件夹
            results.AddRange(new DirectoryInfo(search).GetDirectories().AsParallel().Select(dir =>
            {
                if ((dir.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden) return null;

                int score = 0;
                if (incompleteName.Length > 0)
                {
                    score =Math.Max(StringMatcher.Score(dir.Name.ToLower(), incompleteName), StringMatcher.ScoreForPinyin(dir.Name.ToLower(), incompleteName));
                    if (score == 0) return null;
                }

                return new Result
                {
                    Title = dir.Name,
                    IcoPath = dir.FullName,
                    SubTitle = dir.FullName,
                    Score = score,
                    Action = c =>
                    {
                        _context.API.ChangeQuery($"{query.ActionKeyword} {dir.FullName}\\");
                        return false;
                    }
                };
            }).Where(r => r != null));

            //检索子文件
            results.AddRange(new DirectoryInfo(search).GetFiles().AsParallel().Select(file =>
            {
                if ((file.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden) return null;

                int score = 0;
                if (incompleteName.Length > 0)
                {
                    score =Math.Max(StringMatcher.Score(file.Name.ToLower(), incompleteName), StringMatcher.ScoreForPinyin(file.Name.ToLower(), incompleteName));
                    if (score == 0) return null;
                }

                return new Result
                {
                    Title = Path.GetFileName(file.FullName),
                    SubTitle= file.FullName,
                    IcoPath = file.FullName,
                    Score = score,
                    Action = c =>
                    {
                        Process.Start(file.FullName);
                        return true;
                    }
                };
            }).Where(r => r != null));

            return results;
        }



        public PluginMetadata Metadata()
        {
            return metadata;
        }

    }
}